package com.nulstudio.cloud.common.entity;

import com.nulstudio.cloud.common.exception.NulException;
import com.nulstudio.cloud.common.exception.NulExceptionConstants;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import java.util.Objects;

/**
 * User information.
 * @author nullsty
 * @since 2.0
 */
public final class NulUserDetail {

    /**
     * Unknown gender.
     */
    public static final int GENDER_UNKNOWN = 0;

    /**
     * Male.
     */
    public static final int GENDER_MALE = 1;

    /**
     * Female.
     */
    public static final int GENDER_FEMALE = 2;

    /**
     * ID of the user.
     */
    private int uid;

    /**
     * Gender of the user, 1 represents male, 2 represents female, otherwise 0.
     */
    private int gender;

    /**
     * Username, must be unique.
     */
    private String userName;

    /**
     * Name of the user, not necessary to be unique.
     */
    private String name;

    /**
     * BCrypt encrypted password.
     */
    private String password;

    /**
     * Role ID of the user.
     */
    private int role;

    /**
     * Create an empty {@code NulUser} with fields initialized with null values.
     */
    public NulUserDetail() {
        this.uid = 0;
        this.gender = 0;
        this.userName = null;
        this.name = null;
        this.password = null;
        this.role = 0;
    }

    /**
     * Create a full initialized {@code NulUser} object.
     * @param gender gender of the user, 1 represents male, 2 represents female, otherwise 0
     * @param userName username, must be unique
     * @param name name of the user, not necessary to be unique
     * @param password BCrypt encrypted password
     * @param role role id of the user
     */
    public NulUserDetail(int gender, String userName, String name, String password, int role) {
        this.uid = 0;
        this.gender = gender;
        this.userName = userName;
        this.name = name;
        this.password = password;
        this.role = role;
    }

    /**
     * Create a {@code NulUser} object without password.
     * @param uid id of the user
     * @param userName username, must be unique
     * @param name name of the user, not necessary to be unique
     * @param gender gender of the user, 1 represents male, 2 represents female, otherwise 0
     * @param role role id of the user
     */
    public NulUserDetail(int uid, @NonNull String userName, @NonNull String name, int gender, int role) {
        this.uid = uid;
        this.userName = userName;
        this.name = name;
        this.password = null;
        this.gender = gender;
        this.role = role;
    }

    public static void assertValidity(@Nullable NulUserDetail userDetail) throws NulException {
        if (userDetail == null)
            throw new NulException(NulExceptionConstants.USER_NOT_EXIST);
        if (userDetail.gender != GENDER_MALE && userDetail.gender != GENDER_FEMALE)
            throw new NulException(NulExceptionConstants.INVALID_GENDER);
    }

    /**
     * Get ID of the user.
     * @return ID of the user
     */
    public int getUid() {
        return uid;
    }

    /**
     * Get gender of the user.
     * @return gender of the user, 1 represents male, 2 represents female, otherwise 0
     */
    public int getGender() {
        return gender;
    }

    /**
     * Get username.
     * @return username of the user
     */
    public String getUserName() {
        return userName;
    }

    /**
     * Get name of the user.
     * @return name of the user
     */
    public String getName() {
        return name;
    }

    /**
     * Get BCrypt encrypted password.
     * @return BCrypt encrypted password
     */
    public String getPassword() {
        return password;
    }

    /**
     * Get role name of the user.
     * @return role name of the user
     */
    public int getRole() {
        return role;
    }

    private void setUid(int uid) {
        this.uid = uid;
    }

    private void setGender(int gender) {
        this.gender = gender;
    }

    private void setUserName(String userName) {
        this.userName = userName;
    }

    private void setName(String name) {
        this.name = name;
    }

    private void setPassword(String password) {
        this.password = password;
    }

    private void setRole(int role) {
        this.role = role;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        final NulUserDetail nulUserDetail = (NulUserDetail) o;
        return uid == nulUserDetail.uid && gender == nulUserDetail.gender && Objects.equals(userName, nulUserDetail.userName)
                && Objects.equals(name, nulUserDetail.name) && Objects.equals(password, nulUserDetail.password)
                && Objects.equals(role, nulUserDetail.role);
    }

    @Override
    public int hashCode() {
        return Objects.hash(uid, gender, userName, name, password, role);
    }
}
